import os
import re
import sys
import time

from share import SI
from win_codehelper import CodeHelper


class WinLoadTest(CodeHelper):
    FileUI = 'ui/loadtest.ui'
    Title = '压力测试场景'
    Folder = 'loadtest'


    CodeSnippets = [
    {
        'name': '启动3个客户端',
        'code': '''createClients(
    'client_1', # 客户端名称
    3,       # 客户端数量
    0.1,     # 启动间隔时间，秒
    )
'''
    },

    {
        'name': '启动3个客户端，反复执行',
        'code': '''createClientsAndKeep(
    'client_1', # 客户端名称
    3,       # 客户端数量
    0.1,     # 启动间隔时间，秒
    )
'''
    },

    {
        'name': '启动3个带参数客户端',
        'code': '''# 定义每个客户端对应的参数
args = ['user1','user2','user3']

createClients(
    'client_1', # 客户端名称
    3,       # 客户端数量    
    1,       # 启动间隔时间，秒
    args # 客户端参数
    )
'''
    },

    {
        'name': '启动3个带参数客户端，反复执行',
        'code': '''# 定义每个客户端对应的参数
args = ['user1','user2','user3']

createClientsAndKeep(
    'client_1', # 客户端名称
    3,       # 客户端数量    
    1,       # 启动间隔时间，秒
    args # 客户端参数
    )
'''
    },

    {
        'name': '等待10秒',
        'code': '''
sleep(10)
    '''
    },
    ]
    TestFileTopLines = '''
from gevent import monkey
monkey.patch_all()

from gevent import spawn
import gevent

import time
from pprint import pprint
from time import sleep

from hyload.stats import Stats
from hyload.logger import TestLogger

from hyload.httpclient import HttpClient

clientName2Func = {}

# 如果 args 有值，一定是列表，元素依次赋值给每次clientfunc调用
def createClients(clientName, clientNum, interval, args=None):
    clientFunc = clientName2Func[clientName]
    for i in range(clientNum):
        if args:
            spawn(clientFunc, args[i])
        else:
            spawn(clientFunc)

        if i < clientNum - 1:
            sleep(interval)

# 如果 args 有值，一定是列表，元素依次赋值给每次clientfunc调用
def createClientsAndKeep(clientName, clientNum, interval, args=None):
    clientFunc = clientName2Func[clientName]

    def realFunc(args=None):
        while True:
            try:
                clientFunc(args)
            except Exception as e:
                print(e)

    for i in range(clientNum):
        if args:
            spawn(realFunc, args[i])
        else:
            spawn(realFunc)

        if i < clientNum - 1:
            sleep(interval)

Stats.start()

################## write your code  * begin * ###################

'''

    TestFileBottomLines = '''

################## write your code * end * ###################

gevent.wait()
'''
    def __init__(self):
        super().__init__()
        self.ui.actionShell.triggered.connect(self.CreateLoadScript)

    def CreateLoadScript(self):
        pyFile = os.path.join(SI.WorkFilePath, 'run.py')
        if os.path.exists(pyFile):
            os.remove(pyFile)

        # 先确保文件内容保存了
        self.ActionSaveFile()

        code = self.ui.textEdit.toPlainText()

        #正则表达式搜索使用的client
        pattern = "createClients\w*\(.*?'(.*?)'"

        clientNames = re.findall(pattern,code, re.DOTALL)

        # 把client内容放到函数定义中
        preCode = '\n\n'

        for clientName in clientNames:
            funcName = clientName.replace('-','_')

            cliFullPath = os.path.join(SI.WorkFilePath,'client',clientName+'.py')
            if not os.path.exists(cliFullPath):
                self.LogInfo(f'项目目录中找不到 {cliFullPath} ！！！')
                return False

            preCode += f'def {funcName}(arg=None):\n'


            # 读取client代码
            with open(cliFullPath,encoding='utf8') as f:
                content = f.read()
            lines = content.splitlines()
            for line in lines:
                # 每行缩进4个空格
                preCode += f'    {line}\n'


            preCode += '\n'
            preCode += f'''clientName2Func['{clientName}'] = {funcName}'''
            preCode += '\n\n'


        # 加上函数定义到代码中
        newCode = preCode + code

        # 加上开头、结尾的一些固定代码行，主要是导入必须的名字
        newCode = self.TestFileTopLines + newCode + self.TestFileBottomLines



        # 产生load测试代码文件
        with open(pyFile, 'w', encoding='utf8') as f:
            f.write(newCode)

        self.LogInfo(f'产生性能测试代码文件 {pyFile}')

        return True
    def ActionRun(self):

        if not self.CreateLoadScript():
            return

        cmd = f'cd /d {SI.WorkFilePath} &&start call "{sys.executable}" run.py console=127.0.0.1:{SI.ListenPort}'

        ts = time.strftime('%Y%m%d-%H%M%S', time.localtime())
        para_statsFile = f" statsfile={SI.WorkFilePath}/stats_perf/{ts}.sts"
        cmd += para_statsFile

        self.LogInfo(f'运行 {cmd}')
        os.system(cmd)
